#include<iostream>
#include<string>
#include<sys/types.h>
#include<sys/time.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/stat.h>
#include<cstdio>
#include<cstring>
#include<fcntl.h>
#include<signal.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<vector>
#include<arpa/inet.h>
#include<sys/wait.h>
#include<functional>
#include <semaphore.h>
#include<jsoncpp/json/json.h>
#include<sys/select.h>
#include"Log.hpp"

using namespace std;
#define BACKLOG 5
const static int PORT=8081;
class TcpServer
{
private:
    static TcpServer* tcpserver;
public:
    TcpServer(int port=PORT)
    :_port(port)
    {
       initial();
    }
    static TcpServer* getserver(int port=PORT)
    {
        static pthread_mutex_t mutex;
        pthread_mutex_init(&mutex,nullptr);
        if(tcpserver==nullptr)
        {
            pthread_mutex_lock(&mutex);
            tcpserver=new TcpServer(port);
            pthread_mutex_unlock(&mutex);
        }
        return tcpserver;
    }
    void initial()
    {
        Socket();
        Bind();
        Listen();
        LOG(INFO,"initial success");
    }
    void Socket()
    {
        _listensock=socket(AF_INET,SOCK_STREAM,0);
        if(_listensock<0)
        {
         LOG(FATAL,"socket failed");
            exit(1);
        }
       LOG(INFO,"socket success");
        int opt=1;
        setsockopt(_listensock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); 
    }
    void Bind()
    {
        struct sockaddr_in local;
        local.sin_family=AF_INET;
        local.sin_port=htons(_port);
        local.sin_addr.s_addr=INADDR_ANY;
        if(bind(_listensock,(struct sockaddr*)&local,sizeof(local))<0)
        {
          LOG(FATAL,"binf failed");
            exit(2);
        }
        LOG(INFO,"bind success");

    }
    void Listen()
    {
        int l=listen(_listensock,BACKLOG);
        if(l<0)
        {
           LOG(FATAL,"listen success");
            exit(3);
        }
       LOG(INFO,"listen success");
    }
    int Sock()
    {
        return _listensock;
    }
private:
    int _port;
    int _listensock;
};
 TcpServer* TcpServer::tcpserver=nullptr;